const defaults = Object.freeze({
    ignoreUnknown: false,
    respectType: false,
    respectFunctionNames: false,
    respectFunctionProperties: false,
    unorderedObjects: true,
    unorderedArrays: false,
    unorderedSets: false,
    excludeKeys: void 0,
    excludeValues: void 0,
    replacer: void 0,
});
function objectHash(object, options) {
    if (options) {
        options = { ...defaults, ...options };
    } else {
        options = defaults;
    }
    const hasher = createHasher(options);
    hasher.dispatch(object);
    return hasher.toString();
}
const defaultPrototypesKeys = Object.freeze(["prototype", "__proto__", "constructor"]);
function createHasher(options) {
    let buff = "";
    let context = /* @__PURE__ */ new Map();
    const write = (str) => {
        buff += str;
    };
    return {
        toString() {
            return buff;
        },
        getContext() {
            return context;
        },
        dispatch(value) {
            if (options.replacer) {
                value = options.replacer(value);
            }
            const type = value === null ? "null" : typeof value;
            return this[type](value);
        },
        object(object) {
            if (object && typeof object.toJSON === "function") {
                return this.object(object.toJSON());
            }
            const objString = Object.prototype.toString.call(object);
            let objType = "";
            const objectLength = objString.length;
            if (objectLength < 10) {
                objType = "unknown:[" + objString + "]";
            } else {
                objType = objString.slice(8, objectLength - 1);
            }
            objType = objType.toLowerCase();
            let objectNumber = null;
            if ((objectNumber = context.get(object)) === void 0) {
                context.set(object, context.size);
            } else {
                return this.dispatch("[CIRCULAR:" + objectNumber + "]");
            }
            if (typeof Buffer !== "undefined" && Buffer.isBuffer && Buffer.isBuffer(object)) {
                write("buffer:");
                return write(object.toString("utf8"));
            }
            if (objType !== "object" && objType !== "function" && objType !== "asyncfunction") {
                if (this[objType]) {
                    this[objType](object);
                } else if (!options.ignoreUnknown) {
                    this.unkown(object, objType);
                }
            } else {
                let keys = Object.keys(object);
                if (options.unorderedObjects) {
                    keys = keys.sort();
                }
                let extraKeys = [];
                if (options.respectType !== false && !isNativeFunction(object)) {
                    extraKeys = defaultPrototypesKeys;
                }
                if (options.excludeKeys) {
                    keys = keys.filter((key) => {
                        return !options.excludeKeys(key);
                    });
                    extraKeys = extraKeys.filter((key) => {
                        return !options.excludeKeys(key);
                    });
                }
                write("object:" + (keys.length + extraKeys.length) + ":");
                const dispatchForKey = (key) => {
                    this.dispatch(key);
                    write(":");
                    if (!options.excludeValues) {
                        this.dispatch(object[key]);
                    }
                    write(",");
                };
                for (const key of keys) {
                    dispatchForKey(key);
                }
                for (const key of extraKeys) {
                    dispatchForKey(key);
                }
            }
        },
        array(arr, unordered) {
            unordered = unordered === void 0 ? options.unorderedArrays !== false : unordered;
            write("array:" + arr.length + ":");
            if (!unordered || arr.length <= 1) {
                for (const entry of arr) {
                    this.dispatch(entry);
                }
                return;
            }
            const contextAdditions = /* @__PURE__ */ new Map();
            const entries = arr.map((entry) => {
                const hasher = createHasher(options);
                hasher.dispatch(entry);
                for (const [key, value] of hasher.getContext()) {
                    contextAdditions.set(key, value);
                }
                return hasher.toString();
            });
            context = contextAdditions;
            entries.sort();
            return this.array(entries, false);
        },
        date(date) {
            return write("date:" + date.toJSON());
        },
        symbol(sym) {
            return write("symbol:" + sym.toString());
        },
        unkown(value, type) {
            write(type);
            if (!value) {
                return;
            }
            write(":");
            if (value && typeof value.entries === "function") {
                return this.array(
                    Array.from(value.entries()),
                    true,
                    /* ordered */
                );
            }
        },
        error(err) {
            return write("error:" + err.toString());
        },
        boolean(bool) {
            return write("bool:" + bool);
        },
        string(string) {
            write("string:" + string.length + ":");
            write(string);
        },
        function(fn) {
            write("fn:");
            if (isNativeFunction(fn)) {
                this.dispatch("[native]");
            } else {
                this.dispatch(fn.toString());
            }
            if (options.respectFunctionNames !== false) {
                this.dispatch("function-name:" + String(fn.name));
            }
            if (options.respectFunctionProperties) {
                this.object(fn);
            }
        },
        number(number) {
            return write("number:" + number);
        },
        xml(xml) {
            return write("xml:" + xml.toString());
        },
        null() {
            return write("Null");
        },
        undefined() {
            return write("Undefined");
        },
        regexp(regex) {
            return write("regex:" + regex.toString());
        },
        uint8array(arr) {
            write("uint8array:");
            return this.dispatch(Array.prototype.slice.call(arr));
        },
        uint8clampedarray(arr) {
            write("uint8clampedarray:");
            return this.dispatch(Array.prototype.slice.call(arr));
        },
        int8array(arr) {
            write("int8array:");
            return this.dispatch(Array.prototype.slice.call(arr));
        },
        uint16array(arr) {
            write("uint16array:");
            return this.dispatch(Array.prototype.slice.call(arr));
        },
        int16array(arr) {
            write("int16array:");
            return this.dispatch(Array.prototype.slice.call(arr));
        },
        uint32array(arr) {
            write("uint32array:");
            return this.dispatch(Array.prototype.slice.call(arr));
        },
        int32array(arr) {
            write("int32array:");
            return this.dispatch(Array.prototype.slice.call(arr));
        },
        float32array(arr) {
            write("float32array:");
            return this.dispatch(Array.prototype.slice.call(arr));
        },
        float64array(arr) {
            write("float64array:");
            return this.dispatch(Array.prototype.slice.call(arr));
        },
        arraybuffer(arr) {
            write("arraybuffer:");
            return this.dispatch(new Uint8Array(arr));
        },
        url(url) {
            return write("url:" + url.toString());
        },
        map(map) {
            write("map:");
            const arr = [...map];
            return this.array(arr, options.unorderedSets !== false);
        },
        set(set) {
            write("set:");
            const arr = [...set];
            return this.array(arr, options.unorderedSets !== false);
        },
        file(file) {
            write("file:");
            return this.dispatch([file.name, file.size, file.type, file.lastModfied]);
        },
        blob() {
            if (options.ignoreUnknown) {
                return write("[blob]");
            }
            throw new Error('Hashing Blob objects is currently not supported\nUse "options.replacer" or "options.ignoreUnknown"\n');
        },
        domwindow() {
            return write("domwindow");
        },
        bigint(number) {
            return write("bigint:" + number.toString());
        },
        /* Node.js standard native objects */
        process() {
            return write("process");
        },
        timer() {
            return write("timer");
        },
        pipe() {
            return write("pipe");
        },
        tcp() {
            return write("tcp");
        },
        udp() {
            return write("udp");
        },
        tty() {
            return write("tty");
        },
        statwatcher() {
            return write("statwatcher");
        },
        securecontext() {
            return write("securecontext");
        },
        connection() {
            return write("connection");
        },
        zlib() {
            return write("zlib");
        },
        context() {
            return write("context");
        },
        nodescript() {
            return write("nodescript");
        },
        httpparser() {
            return write("httpparser");
        },
        dataview() {
            return write("dataview");
        },
        signal() {
            return write("signal");
        },
        fsevent() {
            return write("fsevent");
        },
        tlswrap() {
            return write("tlswrap");
        },
    };
}
const nativeFunc = "[native code] }";
const nativeFuncLength = nativeFunc.length;
function isNativeFunction(f) {
    if (typeof f !== "function") {
        return false;
    }
    return Function.prototype.toString.call(f).slice(-nativeFuncLength) === nativeFunc;
}

class WordArray {
    constructor(words, sigBytes) {
        words = this.words = words || [];
        this.sigBytes = sigBytes === void 0 ? words.length * 4 : sigBytes;
    }
    toString(encoder) {
        return (encoder || Hex).stringify(this);
    }
    concat(wordArray) {
        this.clamp();
        if (this.sigBytes % 4) {
            for (let i = 0; i < wordArray.sigBytes; i++) {
                const thatByte = (wordArray.words[i >>> 2] >>> (24 - (i % 4) * 8)) & 255;
                this.words[(this.sigBytes + i) >>> 2] |= thatByte << (24 - ((this.sigBytes + i) % 4) * 8);
            }
        } else {
            for (let j = 0; j < wordArray.sigBytes; j += 4) {
                this.words[(this.sigBytes + j) >>> 2] = wordArray.words[j >>> 2];
            }
        }
        this.sigBytes += wordArray.sigBytes;
        return this;
    }
    clamp() {
        this.words[this.sigBytes >>> 2] &= 4294967295 << (32 - (this.sigBytes % 4) * 8);
        this.words.length = Math.ceil(this.sigBytes / 4);
    }
    clone() {
        return new WordArray([...this.words]);
    }
}
const Hex = {
    stringify(wordArray) {
        const hexChars = [];
        for (let i = 0; i < wordArray.sigBytes; i++) {
            const bite = (wordArray.words[i >>> 2] >>> (24 - (i % 4) * 8)) & 255;
            hexChars.push((bite >>> 4).toString(16), (bite & 15).toString(16));
        }
        return hexChars.join("");
    },
};
const Base64 = {
    stringify(wordArray) {
        const keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
        const base64Chars = [];
        for (let i = 0; i < wordArray.sigBytes; i += 3) {
            const byte1 = (wordArray.words[i >>> 2] >>> (24 - (i % 4) * 8)) & 255;
            const byte2 = (wordArray.words[(i + 1) >>> 2] >>> (24 - ((i + 1) % 4) * 8)) & 255;
            const byte3 = (wordArray.words[(i + 2) >>> 2] >>> (24 - ((i + 2) % 4) * 8)) & 255;
            const triplet = (byte1 << 16) | (byte2 << 8) | byte3;
            for (let j = 0; j < 4 && i * 8 + j * 6 < wordArray.sigBytes * 8; j++) {
                base64Chars.push(keyStr.charAt((triplet >>> (6 * (3 - j))) & 63));
            }
        }
        return base64Chars.join("");
    },
};
const Latin1 = {
    parse(latin1Str) {
        const latin1StrLength = latin1Str.length;
        const words = [];
        for (let i = 0; i < latin1StrLength; i++) {
            words[i >>> 2] |= (latin1Str.charCodeAt(i) & 255) << (24 - (i % 4) * 8);
        }
        return new WordArray(words, latin1StrLength);
    },
};
const Utf8 = {
    parse(utf8Str) {
        return Latin1.parse(unescape(encodeURIComponent(utf8Str)));
    },
};
class BufferedBlockAlgorithm {
    constructor() {
        this._data = new WordArray();
        this._nDataBytes = 0;
        this._minBufferSize = 0;
        this.blockSize = 512 / 32;
    }
    reset() {
        this._data = new WordArray();
        this._nDataBytes = 0;
    }
    _append(data) {
        if (typeof data === "string") {
            data = Utf8.parse(data);
        }
        this._data.concat(data);
        this._nDataBytes += data.sigBytes;
    }
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    _doProcessBlock(_dataWords, _offset) {}
    _process(doFlush) {
        let processedWords;
        let nBlocksReady = this._data.sigBytes / (this.blockSize * 4);
        if (doFlush) {
            nBlocksReady = Math.ceil(nBlocksReady);
        } else {
            nBlocksReady = Math.max((nBlocksReady | 0) - this._minBufferSize, 0);
        }
        const nWordsReady = nBlocksReady * this.blockSize;
        const nBytesReady = Math.min(nWordsReady * 4, this._data.sigBytes);
        if (nWordsReady) {
            for (let offset = 0; offset < nWordsReady; offset += this.blockSize) {
                this._doProcessBlock(this._data.words, offset);
            }
            processedWords = this._data.words.splice(0, nWordsReady);
            this._data.sigBytes -= nBytesReady;
        }
        return new WordArray(processedWords, nBytesReady);
    }
}
class Hasher extends BufferedBlockAlgorithm {
    update(messageUpdate) {
        this._append(messageUpdate);
        this._process();
        return this;
    }
    finalize(messageUpdate) {
        if (messageUpdate) {
            this._append(messageUpdate);
        }
    }
}

const H = [1779033703, -1150833019, 1013904242, -1521486534, 1359893119, -1694144372, 528734635, 1541459225];
const K = [
    1116352408, 1899447441, -1245643825, -373957723, 961987163, 1508970993, -1841331548, -1424204075, -670586216, 310598401, 607225278, 1426881987, 1925078388, -2132889090,
    -1680079193, -1046744716, -459576895, -272742522, 264347078, 604807628, 770255983, 1249150122, 1555081692, 1996064986, -1740746414, -1473132947, -1341970488, -1084653625,
    -958395405, -710438585, 113926993, 338241895, 666307205, 773529912, 1294757372, 1396182291, 1695183700, 1986661051, -2117940946, -1838011259, -1564481375, -1474664885,
    -1035236496, -949202525, -778901479, -694614492, -200395387, 275423344, 430227734, 506948616, 659060556, 883997877, 958139571, 1322822218, 1537002063, 1747873779, 1955562222,
    2024104815, -2067236844, -1933114872, -1866530822, -1538233109, -1090935817, -965641998,
];
const W = [];
class SHA256 extends Hasher {
    constructor() {
        super(...arguments);
        this._hash = new WordArray([...H]);
    }
    reset() {
        super.reset();
        this._hash = new WordArray([...H]);
    }
    _doProcessBlock(M, offset) {
        const H2 = this._hash.words;
        let a = H2[0];
        let b = H2[1];
        let c = H2[2];
        let d = H2[3];
        let e = H2[4];
        let f = H2[5];
        let g = H2[6];
        let h = H2[7];
        for (let i = 0; i < 64; i++) {
            if (i < 16) {
                W[i] = M[offset + i] | 0;
            } else {
                const gamma0x = W[i - 15];
                const gamma0 = ((gamma0x << 25) | (gamma0x >>> 7)) ^ ((gamma0x << 14) | (gamma0x >>> 18)) ^ (gamma0x >>> 3);
                const gamma1x = W[i - 2];
                const gamma1 = ((gamma1x << 15) | (gamma1x >>> 17)) ^ ((gamma1x << 13) | (gamma1x >>> 19)) ^ (gamma1x >>> 10);
                W[i] = gamma0 + W[i - 7] + gamma1 + W[i - 16];
            }
            const ch = (e & f) ^ (~e & g);
            const maj = (a & b) ^ (a & c) ^ (b & c);
            const sigma0 = ((a << 30) | (a >>> 2)) ^ ((a << 19) | (a >>> 13)) ^ ((a << 10) | (a >>> 22));
            const sigma1 = ((e << 26) | (e >>> 6)) ^ ((e << 21) | (e >>> 11)) ^ ((e << 7) | (e >>> 25));
            const t1 = h + sigma1 + ch + K[i] + W[i];
            const t2 = sigma0 + maj;
            h = g;
            g = f;
            f = e;
            e = (d + t1) | 0;
            d = c;
            c = b;
            b = a;
            a = (t1 + t2) | 0;
        }
        H2[0] = (H2[0] + a) | 0;
        H2[1] = (H2[1] + b) | 0;
        H2[2] = (H2[2] + c) | 0;
        H2[3] = (H2[3] + d) | 0;
        H2[4] = (H2[4] + e) | 0;
        H2[5] = (H2[5] + f) | 0;
        H2[6] = (H2[6] + g) | 0;
        H2[7] = (H2[7] + h) | 0;
    }
    finalize(messageUpdate) {
        super.finalize(messageUpdate);
        const nBitsTotal = this._nDataBytes * 8;
        const nBitsLeft = this._data.sigBytes * 8;
        this._data.words[nBitsLeft >>> 5] |= 128 << (24 - (nBitsLeft % 32));
        this._data.words[(((nBitsLeft + 64) >>> 9) << 4) + 14] = Math.floor(nBitsTotal / 4294967296);
        this._data.words[(((nBitsLeft + 64) >>> 9) << 4) + 15] = nBitsTotal;
        this._data.sigBytes = this._data.words.length * 4;
        this._process();
        return this._hash;
    }
}
function sha256base64(message) {
    return new SHA256().finalize(message).toString(Base64);
}

function hash(object, options = {}) {
    const hashed = typeof object === "string" ? object : objectHash(object, options);
    return sha256base64(hashed).slice(0, 10);
}

/* Injected with object hook! */

export { hash, objectHash, sha256base64 };
